#Binary parser template

import os, sys
from Sanae3D.lib.ModelObject import Model3D
from Sanae3D.lib.StructReader import StructReader

class FatalFake_CDT(Model3D):
    
    def __init__(self, obj3D=None, outFile=None, inFile=None):
        
        super(FatalFake_CDT,self).__init__("CDT")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
        self.meshMats = {}
        self.materials = {}
        
    def parse_vertices(self, meshName, numVerts):
        
        for i in xrange(numVerts):
            vx, vy, vz, b1, b2, b3, nx, ny, nz, unk, tu, tv, \
              = self.inFile.read_float(12)
            
            self.create_vertex(meshName, i)
            vx *= -1
            self.add_coords(meshName, i, [vx, vy, vz])
            self.add_vert_uv(meshName, i, [tu, tv])
    
    def parse_faces(self, meshName, numFaces, offset):
        
        for i in xrange(numFaces):
            index = i + offset
            v1, v2, v3 = self.inFile.read_short(3)
            self.create_face(meshName, index)
            self.add_face_verts(meshName, index, [v1, v2, v3])
        
    def write_texture(self, texName, texSize):
        
        texture = open(texName, 'wb')
        texture.write(self.inFile.read(texSize))
        texture.close()
        
    def parse_textures(self):
        
        numTex = self.inFile.read_long()
        for i in xrange(numTex):
            length = self.inFile.read_short()
            texName = self.inFile.read_string(length)
            texName = texName[:-4] + ".dds"
            texSize = self.inFile.read_long()
            self.write_texture(texName, texSize)
    
    def parse_unk1(self):
        
        unkCount = self.inFile.read_long()
        for i in xrange(unkCount):
            self.inFile.read_long()
        unk1 = self.inFile.read_short()
        if unk1 == 0:
            self.inFile.read_float()
        else:
            self.inFile.read_byte(23)
            numCount = self.inFile.read_long()
            for i in xrange(numCount):
                self.inFile.read_float(5)
                self.inFile.read_byte()
            numCount = self.inFile.read_long()
            for i in xrange(numCount):
                self.inFile.read_long(2)
                self.inFile.read_float(8)
            self.inFile.read_byte()
            self.inFile.read_float()
    
    def parse_meshes(self, numMesh):
        
        for i in xrange(numMesh):
            
            length = self.inFile.read_short()
            meshName = self.inFile.read_string(length)
            self.create_object(meshName)
            
            unk1, numVerts = self.inFile.read_long(2)            
            self.inFile.read_byte()
            self.parse_vertices(meshName, numVerts)

            unk2, numSections = self.inFile.read_long(2)            
            faceOffset = 0
            self.meshMats[meshName] = []
            for j in xrange(numSections):
                numFace = self.inFile.read_long() / 3
                self.parse_faces(meshName, numFace, faceOffset)
                self.inFile.read_long()
                length = self.inFile.read_short()
                matName = self.inFile.read_string(length)
                self.meshMats[meshName].append([matName, faceOffset, numFace])
                faceOffset += numFace
            self.parse_unk1()
            
    def parse_materials(self, numMat):
        
        print numMat, "materials"
        for i in xrange(numMat):
            self.inFile.read_float(16)
            self.inFile.read_long()
            length = self.inFile.read_short()
            matName = self.inFile.read_string(length)
            self.inFile.read_long(5)
            numTex = self.inFile.read_long()
            textures = []
            for j in xrange(numTex):
                length = self.inFile.read_short()
                texName = self.inFile.read_string(length)
                textures.append(texName)
                
            self.materials[matName] = i
            self.create_material(i)
            self.add_material_name(i, matName)
            if textures:
                self.add_texture_name(i, textures[0])
                
    def assign_materials(self):
        '''Each key in faceNames gives the mesh it is assigned to, the
        index of the first face with the material, as well as the
        number of faces'''
        
        for meshName in self.meshMats:
            matInfo = self.meshMats[meshName]
            for i in xrange(len(matInfo)):
                matName, offset, number = matInfo[i]
                matIndex = self.materials[matName]
                for j in xrange(offset, offset + number):
                    self.add_face_material(meshName, j, matIndex)
                
                                
    def parse_file(self):
        '''Main parser method'''
        
        self.inFile.read_float(2)
        length = self.inFile.read_short()
        self.inFile.read_string(length)
        numMesh = self.inFile.read_ulong()
        print numMesh, "meshes"
        self.inFile.read_float()
        self.parse_meshes(numMesh)

        #read too much for the last mesh
        self.inFile.seek(-4, 1)
        self.parse_textures()
        
        #materials
        numMat = self.inFile.read_long()
        self.parse_materials(numMat)
        
        #assign materials to faces
        self.assign_materials()
        
        #frames?
        self.inFile.read_long()
        
        print self.inFile.tell()
        
def read_file(path):
    '''Read the file'''
    
    openFile = StructReader(open(path, 'rb'))
    obj = FatalFake_CDT(inFile=openFile)
    obj.parse_file()
    openFile.close()
    return obj

def write_file(path):
    
    pass

def definitions():
    '''Return the header, extension, and a description of the format'''
    
    return "", "CDT", "Fatal Fake CDT"

if __name__ == '__main__':
    
    files = ["assassin.cdt", "berserker.cdt"]
    
    obj = read_file(files[1])